package cn.wokoba.dao.adapter.repository;

import cn.wokoba.dao.dao.*;
import cn.wokoba.dao.dao.po.*;
import cn.wokoba.dao.redis.RedissonService;
import cn.wokoba.service.activity.adapter.repository.IActivityRepository;
import cn.wokoba.service.activity.model.entity.UserGroupBuyOrderDetailEntity;
import cn.wokoba.service.activity.model.valobj.DiscountTypeEnum;
import cn.wokoba.service.activity.model.valobj.GroupBuyActivityDiscountVO;
import cn.wokoba.service.activity.model.valobj.SkuVO;
import cn.wokoba.service.activity.model.valobj.TeamStatisticVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import org.redisson.api.RBitSet;
import org.springframework.stereotype.Repository;

import java.util.*;
import java.util.stream.Collectors;

@Repository
public class ActivityRepository implements IActivityRepository {
    @Resource
    private IGroupBuyActivityDao groupBuyActivityDao;
    @Resource
    private IGroupBuyDiscountDao groupBuyDiscountDao;
    @Resource
    private IScSkuActivityDao scSkuActivityDao;
    @Resource
    IGroupBuyOrderDao groupBuyOrderDao;
    @Resource
    IGroupBuyOrderListDao groupBuyOrderListDao;
    @Resource
    ISkuDao skuDao;
    @Resource
    RedissonService redisService;

    @Override
    public GroupBuyActivityDiscountVO queryGroupBuyActivityDiscountVO(Long activityId) {
        //查询有效的活动
        GroupBuyActivity groupBuyActivityRes = groupBuyActivityDao.selectOne(Wrappers.<GroupBuyActivity>lambdaQuery()
                .eq(GroupBuyActivity::getActivityId, activityId)
                .eq(GroupBuyActivity::getStatus, 1));

        String discountId = groupBuyActivityRes.getDiscountId();

        //查询活动的折扣信息
        LambdaQueryWrapper<GroupBuyDiscount> groupBuyDiscountLambdaQueryWrapper = Wrappers.<GroupBuyDiscount>lambdaQuery();
        groupBuyDiscountLambdaQueryWrapper.eq(GroupBuyDiscount::getDiscountId, discountId);
        GroupBuyDiscount groupBuyDiscountRes = groupBuyDiscountDao.selectOne(groupBuyDiscountLambdaQueryWrapper);

        if (groupBuyDiscountRes == null) return null;

        //组装返回VO
        GroupBuyActivityDiscountVO.GroupBuyDiscount groupBuyDiscount = GroupBuyActivityDiscountVO.GroupBuyDiscount.builder()
                .discountName(groupBuyDiscountRes.getDiscountName())
                .discountDesc(groupBuyDiscountRes.getDiscountDesc())
                .discountType(DiscountTypeEnum.get(groupBuyDiscountRes.getDiscountType()))
                .marketPlan(groupBuyDiscountRes.getMarketPlan())
                .marketExpr(groupBuyDiscountRes.getMarketExpr())
                .tagId(groupBuyDiscountRes.getTagId())
                .build();

        return GroupBuyActivityDiscountVO.builder()
                .activityId(groupBuyActivityRes.getActivityId())
                .activityName(groupBuyActivityRes.getActivityName())
                .groupBuyDiscount(groupBuyDiscount)
                .groupType(groupBuyActivityRes.getGroupType())
                .takeLimitCount(groupBuyActivityRes.getTakeLimitCount())
                .target(groupBuyActivityRes.getTarget())
                .validTime(groupBuyActivityRes.getValidTime())
                .status(groupBuyActivityRes.getStatus())
                .startTime(groupBuyActivityRes.getStartTime())
                .endTime(groupBuyActivityRes.getEndTime())
                .tagId(groupBuyActivityRes.getTagId())
                .tagScope(groupBuyActivityRes.getTagScope())
                .build();
    }

    @Override
    public SkuVO querySkuByGoodsId(String goodsId) {
        Sku sku = skuDao.querySkuByGoodsId(goodsId);
        return null == sku ? null : SkuVO.builder()
                .goodsId(sku.getGoodsId())
                .goodsName(sku.getGoodsName())
                .originalPrice(sku.getOriginalPrice())
                .build();
    }

    @Override
    public Long queryScSkuActivityBySCGoodsId(String source, String channel, String goodsId) {
        ScSkuActivity scSkuActivity = scSkuActivityDao.selectOne(Wrappers.<ScSkuActivity>lambdaQuery()
                .eq(ScSkuActivity::getGoodsId, goodsId)
                .eq(ScSkuActivity::getSource, source)
                .eq(ScSkuActivity::getChannel, channel));
        return null == scSkuActivity ? null : scSkuActivity.getActivityId();
    }

    @Override
    public boolean isTagCrowdRange(String tagId, String userId) {
        RBitSet bitSet = redisService.getBitSet(tagId);
        if (!bitSet.isExists()) return true;
        // 判断用户是否存在人群中
        return bitSet.get(redisService.getIndexFromUserId(userId));
    }

    //TODO 缓存优化
    @Override
    public List<UserGroupBuyOrderDetailEntity> queryInProgressUserGroupBuyOrderDetailListByOwner(Long activityId, String userId, Integer ownerCount) {
        // 1. 根据用户ID、活动ID，查询用户参与的拼团队伍
        //     select user_id, team_id, out_trade_no
        //        from group_buy_order_list
        //        where activity_id = #{activityId} and user_id = #{userId} and status in (0, 1) and end_time > now()
        //        order by id desc
        //        limit #{count}
        List<GroupBuyOrderList> groupBuyOrderLists = groupBuyOrderListDao.selectList(Wrappers.lambdaQuery(GroupBuyOrderList.class)
                .select(GroupBuyOrderList::getUserId, GroupBuyOrderList::getTeamId, GroupBuyOrderList::getOutTradeNo)
                .eq(GroupBuyOrderList::getActivityId, activityId)
                .eq(GroupBuyOrderList::getUserId, userId)
                .in(GroupBuyOrderList::getStatus, 0, 1)
                .gt(GroupBuyOrderList::getEndTime, new java.util.Date())
                .orderByDesc(GroupBuyOrderList::getId)
                .last("LIMIT " + ownerCount));
        if (null == groupBuyOrderLists || groupBuyOrderLists.isEmpty()) return null;

        // 2. 过滤队伍获取 TeamId
        Set<String> teamIds = groupBuyOrderLists.stream()
                .map(GroupBuyOrderList::getTeamId)
                .filter(teamId -> teamId != null && !teamId.isEmpty()) // 过滤非空和非空字符串
                .collect(Collectors.toSet());

        // 3. 查询队伍明细，组装Map结构
        //     select team_id, activity_id, target_count, complete_count, lock_count, status, valid_start_time, valid_end_time,
        //        notify_url
        //        from group_buy_order
        //        where status = 0 and target_count > lock_count and team_id in
        //        <foreach item="teamId" collection="teamIds" open="(" separator="," close=")">
        //            #{teamId}
        //        </foreach>
        List<GroupBuyOrder> groupBuyOrders = groupBuyOrderDao.selectList(Wrappers.lambdaQuery(GroupBuyOrder.class)
                .select(GroupBuyOrder::getTeamId, GroupBuyOrder::getActivityId, GroupBuyOrder::getTargetCount,
                        GroupBuyOrder::getCompleteCount, GroupBuyOrder::getLockCount, GroupBuyOrder::getStatus,
                        GroupBuyOrder::getValidStartTime, GroupBuyOrder::getValidEndTime, GroupBuyOrder::getNotifyUrl)
                .eq(GroupBuyOrder::getStatus, 0)
                .apply("target_count > lock_count")
                .in(GroupBuyOrder::getTeamId, teamIds));

        if (null == groupBuyOrders || groupBuyOrders.isEmpty()) return null;
        Map<String, GroupBuyOrder> groupBuyOrderMap =
                groupBuyOrders.stream().collect(Collectors.toMap(GroupBuyOrder::getTeamId, order -> order));

        // 4. 转换数据
        return groupBuyOrderLists.stream()
                .map(orderList -> {
                    GroupBuyOrder groupBuyOrder = groupBuyOrderMap.get(orderList.getTeamId());
                    if (groupBuyOrder == null) {
                        return null;
                    }
                    return UserGroupBuyOrderDetailEntity.builder()
                            .userId(orderList.getUserId())
                            .teamId(groupBuyOrder.getTeamId())
                            .activityId(groupBuyOrder.getActivityId())
                            .targetCount(groupBuyOrder.getTargetCount())
                            .completeCount(groupBuyOrder.getCompleteCount())
                            .lockCount(groupBuyOrder.getLockCount())
                            .validStartTime(groupBuyOrder.getValidStartTime())
                            .validEndTime(groupBuyOrder.getValidEndTime())
                            .outTradeNo(orderList.getOutTradeNo())
                            .build();
                })
                .filter(Objects::nonNull) // 过滤掉 null 值
                .collect(Collectors.toList());
    }

    @Override
    public List<UserGroupBuyOrderDetailEntity> queryInProgressUserGroupBuyOrderDetailListByRandom(Long activityId, String userId, Integer randomCount) {
        // 1. 根据用户ID、活动ID，查询用户参与的拼团队伍
        //       select user_id, team_id, out_trade_no
        //        from group_buy_order_list
        //        where
        //            activity_id = #{activityId} and
        //            team_id in (select team_id from group_buy_order where activity_id = #{activityId} and status = 0) and
        //            user_id != #{userId} and
        //            status in (0, 1)
        //            and end_time > now()
        //        order by id desc
        //        limit #{count}
        List<GroupBuyOrderList> groupBuyOrderLists = groupBuyOrderListDao.selectList(Wrappers.<GroupBuyOrderList>lambdaQuery()
                .select(GroupBuyOrderList::getUserId, GroupBuyOrderList::getTeamId, GroupBuyOrderList::getOutTradeNo)
                .eq(GroupBuyOrderList::getActivityId, activityId)
                .inSql(GroupBuyOrderList::getTeamId,
                        "SELECT team_id FROM group_buy_order WHERE activity_id = " + activityId + " AND status = 0")
                .ne(GroupBuyOrderList::getUserId, userId)
                .in(GroupBuyOrderList::getStatus, 0, 1)
                .gt(GroupBuyOrderList::getEndTime, new Date()) // 过滤掉已结束的订单
                .orderByDesc(GroupBuyOrderList::getId)
                .last("LIMIT " + randomCount));
        if (null == groupBuyOrderLists || groupBuyOrderLists.isEmpty()) return null;

        // 判断总量是否大于 randomCount
        if (groupBuyOrderLists.size() > randomCount) {
            // 随机打乱列表
            Collections.shuffle(groupBuyOrderLists);
            // 获取前 randomCount 个元素
            groupBuyOrderLists = groupBuyOrderLists.subList(0, randomCount);
        }

        // 2. 过滤队伍获取 TeamId
        Set<String> teamIds = groupBuyOrderLists.stream()
                .map(GroupBuyOrderList::getTeamId)
                .filter(teamId -> teamId != null && !teamId.isEmpty()) // 过滤非空和非空字符串
                .collect(Collectors.toSet());

        // 3. 查询队伍明细，组装Map结构
        //     select team_id, activity_id, target_count, complete_count, lock_count, status, valid_start_time, valid_end_time,
        //        notify_url
        //        from group_buy_order
        //        where status = 0 and target_count > lock_count and team_id in
        //        <foreach item="teamId" collection="teamIds" open="(" separator="," close=")">
        //            #{teamId}
        //        </foreach>
        List<GroupBuyOrder> groupBuyOrders = groupBuyOrderDao.selectList(Wrappers.lambdaQuery(GroupBuyOrder.class)
                .select(GroupBuyOrder::getTeamId, GroupBuyOrder::getActivityId, GroupBuyOrder::getTargetCount,
                        GroupBuyOrder::getCompleteCount, GroupBuyOrder::getLockCount, GroupBuyOrder::getStatus,
                        GroupBuyOrder::getValidStartTime, GroupBuyOrder::getValidEndTime, GroupBuyOrder::getNotifyUrl)
                .eq(GroupBuyOrder::getStatus, 0)
                .apply("target_count > lock_count")
                .in(GroupBuyOrder::getTeamId, teamIds));

        if (null == groupBuyOrders || groupBuyOrders.isEmpty()) return null;
        Map<String, GroupBuyOrder> groupBuyOrderMap =
                groupBuyOrders.stream().collect(Collectors.toMap(GroupBuyOrder::getTeamId, order -> order));

        // 4. 转换数据
        return groupBuyOrderLists.stream()
                .map(orderList -> {
                    GroupBuyOrder groupBuyOrder = groupBuyOrderMap.get(orderList.getTeamId());
                    if (groupBuyOrder == null) {
                        return null;
                    }
                    return UserGroupBuyOrderDetailEntity.builder()
                            .userId(orderList.getUserId())
                            .teamId(groupBuyOrder.getTeamId())
                            .activityId(groupBuyOrder.getActivityId())
                            .targetCount(groupBuyOrder.getTargetCount())
                            .completeCount(groupBuyOrder.getCompleteCount())
                            .lockCount(groupBuyOrder.getLockCount())
                            .validStartTime(groupBuyOrder.getValidStartTime())
                            .validEndTime(groupBuyOrder.getValidEndTime())
                            .outTradeNo(orderList.getOutTradeNo())
                            .build();
                })
                .filter(Objects::nonNull) // 过滤掉 null 值
                .collect(Collectors.toList());
    }

    @Override
    public TeamStatisticVO queryTeamStatisticByActivityId(Long activityId) {
        // 1. 根据活动ID查询拼团队伍
        List<GroupBuyOrderList> groupBuyOrderLists = groupBuyOrderListDao.selectList(Wrappers.<GroupBuyOrderList>lambdaQuery()
                .select(GroupBuyOrderList::getTeamId)
                .eq(GroupBuyOrderList::getActivityId, activityId)
                .in(GroupBuyOrderList::getStatus, 0, 1)
                .groupBy(GroupBuyOrderList::getTeamId));
        if (null == groupBuyOrderLists || groupBuyOrderLists.isEmpty()) {
            return new TeamStatisticVO(0, 0, 0);
        }

        // 2. 过滤队伍获取 TeamId
        Set<String> teamIds = groupBuyOrderLists.stream()
                .map(GroupBuyOrderList::getTeamId)
                .filter(teamId -> !teamId.isEmpty())
                .collect(Collectors.toSet());

        // 3. 统计数据
        Long allTeamCount = groupBuyOrderDao.selectCount(Wrappers.<GroupBuyOrder>lambdaQuery()
                .in(GroupBuyOrder::getTeamId, teamIds));
        Long allTeamCompleteCount = groupBuyOrderDao.selectCount(Wrappers.<GroupBuyOrder>lambdaQuery()
                .eq(GroupBuyOrder::getStatus, 1)
                .in(GroupBuyOrder::getTeamId, teamIds));


        Integer allTeamUserCount = groupBuyOrderDao.selectOne(Wrappers.<GroupBuyOrder>query()
                .select("SUM(lock_count) as lock_count")
                .in("team_id", teamIds)).getLockCount();

        // 4. 构建对象
        return TeamStatisticVO.builder()
                .allTeamCount(Math.toIntExact(allTeamCount))
                .allTeamCompleteCount(Math.toIntExact(allTeamCompleteCount))
                .allTeamUserCount(allTeamUserCount)
                .build();
    }


}
